


#ifndef PF_VECTOR_H
#define PF_VECTOR_H

#include <iostream>

#include "lx_define.h"
#include "lx_Export.h"

/**
 * Represents a 3d vector (x/y/z)
 *

 */
class LX_EXPORT PF_Vector {
public:
    PF_Vector();
    PF_Vector(double vx, double vy, double vz=0.0);
    //PF_Vector(double v[]);
    explicit PF_Vector(bool valid);
    ~PF_Vector();

    void set(double vx, double vy, double vz=0.0);
    void setPolar(double radius, double angle);

    double distanceTo(const PF_Vector& v) const;
    double angle() const;
    double angleTo(const PF_Vector& v) const;
    double magnitude() const;
    PF_Vector lerp(const PF_Vector& v, double t) const;

	bool isInWindow(const PF_Vector& firstCorner, const PF_Vector& secondCorner);

    PF_Vector move(PF_Vector offset);
    PF_Vector rotate(double ang);
    PF_Vector rotate(PF_Vector center, double ang);
    PF_Vector scale(PF_Vector factor);
    PF_Vector scale(PF_Vector center, PF_Vector factor);
	PF_Vector mirror(PF_Vector axisPoint1, PF_Vector axisPoint2);

    PF_Vector operator + (const PF_Vector& v) const;
    PF_Vector operator - (const PF_Vector& v) const;
    PF_Vector operator * (double s) const;
    PF_Vector operator / (double s) const;
    PF_Vector operator - () const;

    void operator += (const PF_Vector& v);
    void operator -= (const PF_Vector& v);
    void operator *= (double s);

    bool operator == (const PF_Vector& v) const;
    bool operator != (const PF_Vector& v) const {
        return !operator==(v);
    }

    static PF_Vector minimum(const PF_Vector& v1, const PF_Vector& v2);
    static PF_Vector maximum(const PF_Vector& v1, const PF_Vector& v2);
    static PF_Vector crossP(const PF_Vector& v1, const PF_Vector& v2);
    static double dotP(const PF_Vector& v1, const PF_Vector& v2);

    friend std::ostream& operator << (std::ostream&, const PF_Vector& v);

#ifdef LXCAD_TEST

    static bool test();
#endif

public:
    double x;
    double y;
    double z;
    bool valid;
};


/**
 * Represents one to 4 vectors. Typically used to return multiple
 * solutions from a function.
 */
class LX_EXPORT PF_VectorSolutions {
public:
    PF_VectorSolutions();
    PF_VectorSolutions(const PF_VectorSolutions& s);
    PF_VectorSolutions(int num);
    PF_VectorSolutions(const PF_Vector& v1);
    PF_VectorSolutions(const PF_Vector& v1, const PF_Vector& v2);
    PF_VectorSolutions(const PF_Vector& v1, const PF_Vector& v2,
	                   const PF_Vector& v3);
    PF_VectorSolutions(const PF_Vector& v1, const PF_Vector& v2,
                       const PF_Vector& v3, const PF_Vector& v4);
    PF_VectorSolutions(const PF_Vector& v1, const PF_Vector& v2,
                       const PF_Vector& v3, const PF_Vector& v4,
					   const PF_Vector& v5);
    
	~PF_VectorSolutions();

	void alloc(int num);
    void clean();
    PF_Vector get(int i) const;
	int getNumber() const;
	bool hasValid() const;
	void set(int i, const PF_Vector& v);
	void setTangent(bool t);
    bool isTangent() const;
    PF_Vector getClosest(const PF_Vector& coord, 
			double* dist=NULL, int* index=NULL) const;
    void rotate(PF_Vector center, double ang);
    void scale(PF_Vector center, PF_Vector factor);

	PF_VectorSolutions operator = (const PF_VectorSolutions& s);

    friend std::ostream& operator << (std::ostream& os,
                                      const PF_VectorSolutions& s);

private:
    PF_Vector* vector;
    int num;
    bool tangent;
};

#endif

// EOF
